package com.nebula.salary.portal.controller;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.base.Strings;
import com.nebula.salary.common.constants.Const;
import com.nebula.salary.common.constants.ReturnMessage;
import com.nebula.salary.common.exception.CustomException;
import com.nebula.salary.common.result.ServerResponse;
import com.nebula.salary.common.utils.RedisUtil;
import com.nebula.salary.common.utils.SecurityUtil;
import com.nebula.salary.model.dto.PageDto;
import com.nebula.salary.model.dto.SalaryDto;
import com.nebula.salary.model.pojo.Salary;
import com.nebula.salary.model.vo.LoginUser;
import com.nebula.salary.model.vo.PageResult;
import com.nebula.salary.model.vo.SalaryEditVo;
import com.nebula.salary.model.vo.SalaryVo;
import com.nebula.salary.portal.service.ISalaryService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Arrays;

/**
 * <p>
 * 我的工资
 * </p>
 *
 * @author codex
 * @since 2022-01-24
 */
@RestController
@Api(tags = "我的工资")
@RequestMapping("/salary/my")
@Transactional(rollbackFor = Exception.class)
public class SalaryController {
    
    @Resource
    private ISalaryService salaryService;
    
    @Resource
    private RedisUtil redisUtil;
    
    private static final Log log = LogFactory.get();
    
    @ApiOperation(value = "根据工资ID查询工资", notes = "根据工资ID查询工资")
    @GetMapping("/{salaryId}")
    public ServerResponse<SalaryEditVo> getBySalaryId(
            @ApiParam(value = "工资ID", required = true)
            @PathVariable Long salaryId) {
        
        Salary salary = salaryService.getById(salaryId);
        SalaryEditVo salaryEditVo = new SalaryEditVo();
        BeanUtils.copyProperties(salary, salaryEditVo);
        
        return ServerResponse.createBySuccess(salaryEditVo);
    }
    
    
    @ApiOperation(value = "删除工资", notes = "删除工资")
    @DeleteMapping("/{salaryIds}")
    public ServerResponse<String> delete(@ApiParam(value = "工资ID", required = true)
                                         @PathVariable("salaryIds") Long[] salaryIds) {
        try {
            salaryService.removeByIds(Arrays.asList(salaryIds));
            
            // 删除redis缓存中的工资统计数据
            redisUtil.deleteObject(Const.ANALYZE_RESULT_KEY + SecurityUtil.getLoginUser().getUuid());
            
            return ServerResponse.createBySuccessMessage(ReturnMessage.DELETE_SUCCESS);
        } catch (Exception e) {
            log.error("删除工资出现异常，原因：" + e.getMessage());
            return ServerResponse.createByErrorMessage(ReturnMessage.DELETE_ERROR);
        }
    }
    
    @ApiOperation(value = "修改工资", notes = "修改工资")
    @PutMapping("/")
    public ServerResponse<String> update(@RequestBody SalaryDto salaryDto) {
        checkData(salaryDto, Const.TYPE_UPDATE);
        
        try {
            Salary salary = new Salary();
            BeanUtils.copyProperties(salaryDto, salary);
            salary.setIssueYear(salary.getIssueDate().getYear());
            salary.setIssueMonth(salary.getIssueDate().getMonthValue());
            
            if (Strings.isNullOrEmpty(salary.getRemark())) {
                salary.setRemark(salary.getIssueYear() + "年" + salary.getIssueMonth() + "月份工资");
            }
            
            salaryService.updateById(salary);
            
            // 删除redis缓存中的工资统计数据
            redisUtil.deleteObject(Const.ANALYZE_RESULT_KEY + SecurityUtil.getLoginUser().getUuid());
            
            return ServerResponse.createBySuccessMessage(ReturnMessage.UPDATE_SUCCESS);
        } catch (Exception e) {
            log.error("修改工资失败，原因：" + e.getMessage());
            return ServerResponse.createByErrorMessage(ReturnMessage.UPDATE_ERROR);
        }
    }
    
    @ApiOperation(value = "新增工资", notes = "新增工资")
    @PostMapping("/")
    public ServerResponse<String> add(@RequestBody SalaryDto salaryDto) {
        checkData(salaryDto, Const.TYPE_INSERT);
        try {
            Salary salary = new Salary();
            BeanUtils.copyProperties(salaryDto, salary);
            salary.setUserId(SecurityUtil.getLoginUser().getUser().getUserId());
            salary.setIssueYear(salary.getIssueDate().getYear());
            salary.setIssueMonth(salary.getIssueDate().getMonthValue());
            
            if (Strings.isNullOrEmpty(salary.getRemark())) {
                salary.setRemark(salary.getIssueYear() + "年" + salary.getIssueMonth() + "月份工资");
            }
            
            salaryService.save(salary);
            
            // 删除redis缓存中的工资统计数据
            redisUtil.deleteObject(Const.ANALYZE_RESULT_KEY + SecurityUtil.getLoginUser().getUuid());
            
            return ServerResponse.createBySuccessMessage(ReturnMessage.INSERT_SUCCESS);
        } catch (Exception e) {
            log.error("新增工资失败，原因：" + e.getMessage());
            return ServerResponse.createByErrorMessage(ReturnMessage.INSERT_ERROR);
        }
    }
    
    @ApiOperation(value = "我的工资", notes = "我的工资")
    @GetMapping("/")
    public ServerResponse<PageResult> mySalary() {
        int currentYear = LocalDateTime.now().getYear();
        PageDto pageDto = new PageDto(1L, 12L);
        return salaryService.selectSalaryByYear(currentYear, pageDto);
    }
    
    
    private void checkData(SalaryDto salaryDto, String type) {
        if (salaryDto == null) {
            throw new CustomException(ReturnMessage.ILLEGAL_REQUEST);
        }
        
        if (Const.TYPE_UPDATE.equals(type)) {
            if (salaryDto.getSalaryId() == null) {
                throw new CustomException(ReturnMessage.ILLEGAL_REQUEST);
            }
        }
        
        if (salaryDto.getSalary() == null || salaryDto.getSalary().compareTo(BigDecimal.valueOf(0)) < 0) {
            throw new CustomException("请输入正确的工资");
        }
        
        if (salaryDto.getSalary().compareTo(BigDecimal.valueOf(Const.MAX_SALARY)) > 0) {
            throw new CustomException("输入的工资超限");
        }
        
        if (salaryDto.getIssueDate() == null) {
            throw new CustomException("请输入发放日期");
        }
        
        if (!Strings.isNullOrEmpty(salaryDto.getRemark()) && salaryDto.getRemark().length() > Const.MAX_REMARK_LENGTH) {
            throw new CustomException("备注长度超限");
        }
        
        // 新增
        if (type.equals(Const.TYPE_INSERT)) {
            int count = salaryService.count(new QueryWrapper<Salary>().eq(Salary.ISSUE_YEAR,
                    salaryDto.getIssueDate().getYear()).eq(Salary.USER_ID, SecurityUtil.getLoginUser().getUser().getUserId()));
            if (count >= Const.CURRENT_YEAR_SALARY_MAX_COUNT) {
                throw new CustomException(ReturnMessage.CURRENT_YEAR_SALARY_COUNT_MAX_ERROR);
            }
            
            count = salaryService.count(new QueryWrapper<Salary>().eq(Salary.ISSUE_MONTH,
                    salaryDto.getIssueDate().getMonthValue()).eq(Salary.USER_ID,
                    SecurityUtil.getLoginUser().getUser().getUserId()).eq(Salary.ISSUE_YEAR,
                    salaryDto.getIssueDate().getYear()));
            if (count > 0) {
                throw new CustomException(ReturnMessage.CURRENT_MONTH_SALARY_COUNT_MAX_ERROR);
            }
        }
        
        // 修改
        if (type.equals(Const.TYPE_UPDATE)) {
            QueryWrapper<Salary> wrapper = new QueryWrapper<>();
            wrapper.eq(Salary.USER_ID, SecurityUtil.getLoginUser().getUser().getUserId())
                    .eq(Salary.ISSUE_YEAR, salaryDto.getIssueDate().getYear())
                    .eq(Salary.ISSUE_MONTH, salaryDto.getIssueDate().getMonthValue())
                    .ne(Salary.SALARY_ID, salaryDto.getSalaryId());
            
            int count = salaryService.count(wrapper);
            
            if (count > 0) {
                throw new CustomException(ReturnMessage.CURRENT_MONTH_SALARY_COUNT_MAX_ERROR);
            }
        }
    }
}

